<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>

<div id="test">尚硅谷IT教育</div>

<div id="demo">
  <ul>
    <li>test1</li>
    <li>test2</li>
    <li>test3</li>
  </ul>
</div>



<!--
1. [].slice.call(lis): 将伪数组转换为真数组
2. node.nodeType: 得到节点类型
3. Object.defineProperty(obj, propertyName, {}): 给对象添加属性(指定描述符)
4. Object.keys(obj): 得到对象自身可枚举属性组成的数组
5. obj.hasOwnProperty(prop): 判断prop是否是obj自身的属性
6. DocumentFragment: 文档碎片(高效批量更新多个节点)
-->

<script type="text/javascript">
  // 1. [].slice.call(lis): 将伪数组转换为真数组
  const lis = document.getElementsByTagName('li') // lis是伪数组
  console.log(lis.forEach, lis instanceof Array, Array.isArray(lis))
  const lis2 = Array.from(lis) // es6语法
  console.log(lis2.forEach, lis2 instanceof Array, Array.isArray(lis2))
  lis2.slice()  // [1, 2, 3, 4, 5].slice(1)

  const lis3 = Array.prototype.slice.call(lis) // 相当于obj.slice()
  console.log(lis3.forEach, lis3 instanceof Array, Array.isArray(lis3))


  // Array.prototype.slice2 = function () {
  //   const arr = []
  //   for (let index = 0; index < this.length; index++) {
  //     arr.push(this[index])
  //   }
  //   return arr
  // }


  // 2. node.nodeType: 得到节点类型
  // <div id="test">尚硅谷IT教育</div>
  const elementNode = document.getElementById('test')
  const attrNode = elementNode.getAttributeNode('id')
  const textNode = elementNode.firstChild // textNode.textContent==='尚硅谷IT教育'
  console.log(elementNode.nodeType, attrNode.nodeType, textNode.nodeType)

  // 3. Object.defineProperty(obj, propertyName, {}): 给对象添加属性(指定描述符)
  const p = {
    firstName: 'A',
    lastName: 'B'
  }
  Object.defineProperty(p, 'fullName', { // 属性描述符
    // 数据描述符
    configurable: false, // true/false  是否可以重新define
    enumerable: false, // true/false 是否可以枚举(for..in / keys())
    // value: 'A-B', // 指定初始值
    // writable: false, // true/false value是否可以修改
    // 存取描述符
    get () {
      return this.firstName + '-' + this.lastName
    },
    set (value) {
      const names = value.split('-')
      this.firstName = names[0]
      this.lastName = names[1]
    }
  })

  // 4. Object.keys(obj): 得到对象自身可枚举属性组成的数组
  console.log(Object.keys(p))

  // 5. obj.hasOwnProperty(prop): 判断prop是否是obj自身的属性
  console.log(p.hasOwnProperty('fullName'), p.hasOwnProperty(p.toString))

  // 6. DocumentFragment: 文档碎片(高效批量更新多个节点)
  // 一个fragment对象就是内存中的节点容器(只存在于内存)

  /* 
  <div id="demo">
    <ul>
      <li>atguigu</li>
      <li>atguigu</li>
      <li>atguigu</li>
      <li>atguigu</li>
      <li>atguigu</li>
      <li>atguigu</li>
    </ul>
  </div>
  */

  const div = document.getElementById('demo')
  // 创建空的fragment容器
  const fragment = document.createDocumentFragment()
  // 将div中所有子节点转移为fragment的子节点
  let child
  while(child=div.firstChild) {
    fragment.appendChild(child) // 一个节点只能有一个父节点
  }

  // 处理fragment中所有li
  const lis5 = fragment.children[0].children
  Array.prototype.slice.call(lis5).forEach(li => {
    li.innerHTML = 'atguigu' // 此时不更新界面
  })

  // 将fragment添加为div的子节点
  div.appendChild(fragment) // fragment本身不会进入div, fragment的所有子节点进入div  ==> 此时批量更新





</script>
</body>
</html>